package com.a2v2.online.store.common.aop;

import java.sql.Timestamp;
import java.util.HashMap;
import java.util.Map;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.beans.factory.annotation.Autowired;

import com.a2v2.online.store.common.constant.ServiceConstant;
import com.a2v2.online.store.common.dto.SystemToken;
import com.a2v2.online.store.common.dto.Token;
import com.a2v2.online.store.common.logger.contract.ILogger;
import com.a2v2.online.store.common.type.ChannelType;
import com.a2v2.online.store.service.constant.ErrorCode;
import com.a2v2.online.store.service.dto.AuthenticateResponse;
import com.a2v2.online.store.service.dto.GenericRequest;
import com.a2v2.online.store.service.exception.ServiceException;
@Aspect
public class ServiceAuthenticationInterceptor  {
	@Autowired
	ILogger logger;

	private static final Map<String, Token> cacheToken = new HashMap<String, Token>();

	@AfterReturning(value="com.expresspay.common.aop.SystemPointcut.authenticate()", returning="retObject")
	public void afterReturning(Object retObject) throws Throwable {
		AuthenticateResponse authenticateResponse = (AuthenticateResponse)retObject;
		cacheToken.put(authenticateResponse.getToken().getLoginSessionId(), authenticateResponse.getToken());		
	}

	@AfterReturning(value="com.expresspay.common.aop.SystemPointcut.updateUserSession()", returning="retObject")
	public void beforeUpdateUserSession(JoinPoint jp, Object retObject) throws Throwable {
		Object[] methodArguments = jp.getArgs();
		GenericRequest genericRequest = null;
		Token webToken = null;
		genericRequest = (GenericRequest) methodArguments[0];
		webToken = (Token) genericRequest.getToken();
		Signature s = jp.getSignature();
		cacheToken.remove(webToken.getLoginSessionId());
	}

	@Before(value = "com.expresspay.common.aop.SystemPointcut.authenticateService()")
	public void before(JoinPoint jp) throws Throwable {
		Object[] methodArguments = jp.getArgs();		
		GenericRequest genericRequest = null;
		Token token = null;
		genericRequest = (GenericRequest) methodArguments[0];
		//for null request throw request can not be null
		if ( genericRequest == null ){
			throw new ServiceException(ErrorCode.IESY003);
		}
		token = (Token) genericRequest.getToken();
		//for null web token throw token can not be null
		if ( token == null ){
			throw new ServiceException(ErrorCode.IESY004);
		}
		
		Timestamp cTimestamp = new Timestamp(System.currentTimeMillis());
		if(token instanceof SystemToken)
		{
			SystemToken st = (SystemToken)token;
			st.setLoggedInTime(cTimestamp);
			return;
		}
		long difference = cTimestamp.getTime() - token.getLoggedInTime().getTime();
		long diffInMinutes = difference / (60 * 1000);

		if (!jp.getSignature().getName().equalsIgnoreCase("authenticate")) {
			// for invalid session id throw invalid request 
			if (!(cacheToken.containsKey(token.getLoginSessionId()))) {
				throw new ServiceException(ErrorCode.IESY005);
			}

			if (token.getChannelType().equals(ChannelType.WEB)) {
				if (diffInMinutes > ServiceConstant.WEB) {

				} else {
					token.setLoggedInTime(cTimestamp);
				}

			} else if (token.getChannelType().equals(ChannelType.IVR)) {
				if (diffInMinutes > ServiceConstant.IVR) {

				} else {
					token.setLoggedInTime(cTimestamp);
				}

			}

		}

	}

}
